# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-15
# File     : file_service.py
# Project  : codebuddy_craft
# Desc     : 文件服务

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete
from typing import List, Optional, Dict, Any, BinaryIO
import uuid
import os
from datetime import datetime
import aiofiles
import hashlib

from backend.models.file import File
from backend.schemas.file import FileCreateRequest as FileCreate, FileUpdateRequest as FileUpdate
from backend.utils.logger import get_logger

logger = get_logger(__name__)
from backend.core.settings import get_settings

settings = get_settings()

class FileService:
    """
    文件服务类
    
    处理文件相关的业务逻辑
    """
    
    @staticmethod
    async def create_file(
        db: AsyncSession, 
        file_data: FileCreate, 
        project_id: str, 
        user_id: str,
        file_content: Optional[bytes] = None
    ) -> File:
        """
        创建新文件记录
        """
        file_id = str(uuid.uuid4())
        file_path = file_data.path
        
        # 计算文件哈希值（如果有内容）
        content_hash = None
        if file_content:
            content_hash = hashlib.sha256(file_content).hexdigest()
            
            # 保存文件内容
            upload_dir = os.path.join(settings.UPLOAD_DIR, project_id)
            os.makedirs(upload_dir, exist_ok=True)
            
            file_storage_path = os.path.join(upload_dir, file_id)
            async with aiofiles.open(file_storage_path, 'wb') as f:
                await f.write(file_content)
        
        file = File(
            id=file_id,
            name=file_data.name,
            path=file_path,
            mime_type=file_data.mime_type,
            size=file_data.size,
            project_id=project_id,
            user_id=user_id,
            content_hash=content_hash,
            created_at=datetime.utcnow(),
            updated_at=datetime.utcnow(),
            metadata=file_data.metadata or {}
        )
        
        db.add(file)
        await db.commit()
        await db.refresh(file)
        logger.info(f"Created file: {file.id} in project: {project_id}")
        return file
    
    @staticmethod
    async def get_file(db: AsyncSession, file_id: str) -> Optional[File]:
        """
        获取文件详情
        """
        result = await db.execute(select(File).where(File.id == file_id))
        return result.scalar_one_or_none()
    
    @staticmethod
    async def get_project_files(db: AsyncSession, project_id: str) -> List[File]:
        """
        获取项目的所有文件
        """
        result = await db.execute(
            select(File)
            .where(File.project_id == project_id)
            .order_by(File.path, File.name)
        )
        return result.scalars().all()
    
    @staticmethod
    async def update_file(db: AsyncSession, file_id: str, file_data: FileUpdate) -> Optional[File]:
        """
        更新文件信息
        """
        update_data = file_data.dict(exclude_unset=True)
        update_data["updated_at"] = datetime.utcnow()
        
        await db.execute(
            update(File)
            .where(File.id == file_id)
            .values(**update_data)
        )
        await db.commit()
        
        return await FileService.get_file(db, file_id)
    
    @staticmethod
    async def delete_file(db: AsyncSession, file_id: str) -> bool:
        """
        删除文件
        """
        file = await FileService.get_file(db, file_id)
        if not file:
            return False
            
        # 删除物理文件（如果存在）
        file_storage_path = os.path.join(settings.UPLOAD_DIR, file.project_id, file.id)
        if os.path.exists(file_storage_path):
            os.remove(file_storage_path)
        
        result = await db.execute(delete(File).where(File.id == file_id))
        await db.commit()
        return result.rowcount > 0
    
    @staticmethod
    async def read_file_content(project_id: str, file_id: str) -> Optional[bytes]:
        """
        读取文件内容
        """
        file_path = os.path.join(settings.UPLOAD_DIR, project_id, file_id)
        if not os.path.exists(file_path):
            return None
            
        async with aiofiles.open(file_path, 'rb') as f:
            content = await f.read()
        return content
    
    @staticmethod
    async def write_file_content(project_id: str, file_id: str, content: bytes) -> bool:
        """
        写入文件内容
        """
        upload_dir = os.path.join(settings.UPLOAD_DIR, project_id)
        os.makedirs(upload_dir, exist_ok=True)
        
        file_path = os.path.join(upload_dir, file_id)
        try:
            async with aiofiles.open(file_path, 'wb') as f:
                await f.write(content)
            return True
        except Exception as e:
            logger.error(f"Error writing file {file_id}: {str(e)}")
            return False